/*
 *  usmap.js
 *
 *  @author Tanya L. Crenshaw
 */

/* Define the global namespace and setup all the listners for the main
 * page.  Scroll to the bottom to see listeners get setup.
 */
var cs441GoogleMapsViz = {};

/*
 * cs441GoogleMapsViz.addEvent()
 *
 * A utility function adapted from Google Code university to
 * simplify the browser-dependent act of adding events to
 * html elements.  Given an element, an event, and a function
 * this function checks the browser capability, and uses the
 * correct "add listener" or "attach event" function to
 * bind the function to the event for the element.
 *
 * @param el The html element.
 * @param evt A string representing the event.  e.g. 'click'
 * @param fn The function that will be invoked when the given
 * event 'evt' is experienced by the given element 'el'.
 *
 * @return void
 */
cs441GoogleMapsViz.addEvent = function(el, evt, fn) {
    if(el.addEventListener) {
	el.addEventListener(evt, fn, false);
    } else if(el.attachEvent) {
	el.attachEvent('on' + evt, fn);
    }
};
/* cs441GoogleMapsViz.forEach()
 *
 * A utility function adopted from "Eloquent JavaScript" that
 * accepts an action and applies that action to each element in
 * an array.  This helps to abstract the tedium of for-loops.
 *
 * @param array The array of elements to operate upon.
 * @param action The action to perform on each element.
 *
 * @return void
 */
cs441GoogleMapsViz.forEach = function(array, action) {

    for(var i = 0; i < array.length; i++) {
	action(array[i]);
    }

};
/*
 * cs441GoogleMapsViz.getZip()
 *
 * This function gets the zipcode from the page, as entered by
 * the user in the input textbox with id "zipcode".
 *
 * @param void
 * @return The value of the html element with id "zipcode"
 */
cs441GoogleMapsViz.getZip = function() {
    // TLC TODO: Use the memoization pattern so that the
    // zipcode element only has to be grabbed once.
    return document.getElementById("zipcode").value;
};

/*
 *  cs441GoogleMapsViz.regionalize()
 * 
 *  This function filters an array of layer objects based on the
 *  region name grabbed from the page (that is, entered by the user)
 *  and recenters the map at the region.
 *
 *  @param layerArray An array of Layer objects to regionalize.
 *  @param geocoder The geocoder service to use to recenter the map.
 *  @return void
 */
cs441GoogleMapsViz.regionalize = function(layerArray, geocoder) {

        // Get the region name from the page, as entered by the user.
    var region = $("#state").val();


    // Filter each layer by the region.
    cs441GoogleMapsViz.forEach(layerArray, function(t) {
	console.log("--------");
        cs441GoogleMapsViz.filterByRegion.call(t, region);
    });
    
//    cs441GoogleMapsViz.filterByRegion.call(layerArray[0], region);
//    cs441GoogleMapsViz.filterByRegion.call(layerArray[1], region);

    // Set the zoom.
    layerArray[0].map.setZoom(6);
    
    // Center the map at the state corresponding to the region.
    centerAt(layerArray[0].map, cs441GoogleMapsViz.convertRegionToState(region), geocoder);
}

/*
 *  cs441GoogleMapsViz.lookup()
 *
 *  For an array of layers, this function filters the layers
 *  according to the zipcode grabbed from the page (that is,
 * 	entered by the user) and recenters the layer's map at the zipcode.
 *
 *  This function assumes that all the layers are on the same map.
 *  Thus, when resetting the zoom and recentering the map, these
 *  operations are done only once on the first layer.
 *
 *  @param layerArray An array of Google FusionTableLayers.
 *  @param geocoder The geocoder service to use to recenter the map.
 *  @return void
 */
cs441GoogleMapsViz.lookup = function(layerArray, geocoder) {

    // Get the zip code from the page, as entered by the user.
    var zip = cs441GoogleMapsViz.getZip();
    // Convert the zip code from the page into a corresponding state so that the 
    // encrypted IDs can be looked up in utilities.js
    var state = cs441GoogleMapsViz.convertZipToState(zip);
    // Based on the entered zip code, change the zip and high school layer to have the 
    // EID of the state corresponding to that zip code
    layerArray[0].setEID(cs441GoogleMapsViz.tables["zips"][state])
    layerArray[1].setEID(cs441GoogleMapsViz.tables["schools"][state]);

    // Filter each layer by the zip.
    cs441GoogleMapsViz.forEach(layerArray, function(t) {
	filterByZip.call(t, zip);
    });
    // Set the zoom for each layer.
    layerArray[0].map.setZoom(11);

 
    // Center the map for each layer.
    centerAt(layerArray[0].map, zip, geocoder);
    
	
}

cs441GoogleMapsViz.setStudentLayer = function (studentLayer) {
    var filter = createFilter();
    //    alert(filter);
    //apply the new filter to the student layer.
    studentLayer.ref.setOptions({
	query : {
	    from : studentLayer.getEID(),
	    where: filter
	},
	map : studentLayer.map
    });
}



/*
 *  cs441GoogleMapsViz.toggle()
 *
 *  @param layerArray An array of Layer objects to toggle.
 *  @return void
 */
cs441GoogleMapsViz.toggle = function(layerArray) {

    // Get the zip code from the page, as entered by the user.
    var zip = cs441GoogleMapsViz.getZip();

    // Toggle each layer by the zip.
    cs441GoogleMapsViz.forEach(layerArray, function(t) {
	toggleLayer.call(t, zip);
    });
}
/*
 *  cs441GoogleMapsViz.initialize()
 *
 *  A function to: 1. create a google map centered at the us and
 *  2: instantiate a google maps geocoder service.  Note that the
 *  variables geocoder and map are not declared using var -- this
 *  is so that they can be written to the window object and used by
 *  other functions.
 *
 *  @param void
 *  @return void
 */
cs441GoogleMapsViz.initialize = function() {

    // Encrypted IDs for the two layers

    // The Encrypted ID used below contains zip code information for the 
    // following states: Oregon, Utah, Colorado, Nebraska, and Illinois
    var zipEID = '11aJXuIDW9c9yTiJT2QJ3knmy2ou6YCJLpHzMa0w';
    
    // The Encrypted ID used below is that of
    // OregonHighSchools_withManualFusionTableFixes.csv available
    // in Tanya Crenshaw's public fusion tables.
    //var schoolEID = '1TMA9tSPlSIvJVqdfTP0JuxKJhBejygkVuXZFgKg';
    var schoolEID = '1YcgR53xYb2OQm77NNyYfMh7-nwkrtZxoig7U_ms'; //Crenshaw -> working
    //schoolEID = '144tZzciN0Moo33qJmo0LgtiASHnv1s692vivqGU';
    

    // The Encrypted ID used below is that of the student csv available
    // from Tanya Crenshaw
    var studentEID = "1MpKoIu0SIVNvEILq-HqPHOYbK67akZU-h3jSRHw";

    // Instatiate a new geocoder service
    var geocoder = new google.maps.Geocoder();

    // The center point of the map is Lincoln, NB.
    var usa = new google.maps.LatLng(40.8358, -96.6452);

    // Create a Google Map object centered at usa
    var map = new google.maps.Map(document.getElementById("contig_us_map_canvas"), {
	zoom : 4,
	center : usa,
	mapTypeId : google.maps.MapTypeId.ROADMAP
    });

    // Create a Layer object for the zip code boundary layer.  The
    // first parameter creates the Google FusionTablesLayer object.
    // The Layer is not currently being filtered, so the final
    // parameter is false.
    var zipLayer = new Layer(new google.maps.FusionTablesLayer({
	query : {
	    from : zipEID
	}
    }), zipEID, map, 'ZipCodeArea' /*'ZCTA5CE10'*/, false);

    // Create a Layer object for the high schools layer.  The first
    // parameter creates the Google FusionTablesLayer object.  The
    // Layer is not currently being filtered, so the final parameter
    // is false.
    var schoolLayer = new Layer(new google.maps.FusionTablesLayer({
	query : {
	    from : schoolEID
	},
 	styles: [{
	    markerOptions: {
		iconName: "schools"
	    }
	}]
    }), schoolEID, map, 'Zip', false);


    //Create a layer object for the student layer. 
    var studentLayer =  new Layer(new google.maps.FusionTablesLayer({
	query : {
	    from : studentEID,
	}
    }), studentEID, map, 'Zip', false);

    // Create an array of Layers
    var layerArray = new Array();
    layerArray.push(zipLayer);
    layerArray.push(schoolLayer);
    //layerArray.push(studentLayer);
    
    // Add a listener to the layer.  When the user clicks on the
    // particular zip code area in the layer, some information
    // about the particular zip code is displayed in the info portion
    // of the page.
    google.maps.event.addListener(zipLayer.ref, 'click', function(displayedArea) {

	// Get the necessary information from the clicked area
	var information = displayedArea.row['ZipCodeArea'].value + "<br>";

	// Format and display it in the information window for the displayed area.
	formatInfoWindow(displayedArea, information)
    });
    google.maps.event.addListener(studentLayer.ref, 'click', function(displayedArea) {
	displayedArea.infoWindowHtml = "<strong>ID:</strong> " + 
	    displayedArea.row['UPortland_UniqueID'].value+"<br />" +
	    "<strong>Gender: </strong>" + displayedArea.row['Gender'].value+"<br />" +
	    "<strong>GPA: </strong>" + displayedArea.row['HS_GPA'].value+"<br />" +
	    "<strong>SAT Math: </strong>" + displayedArea.row['SAT_MAth'].value+"<br >" +
	    "<strong>SAT Verbal</strong>: " + displayedArea.row['SAT_Verbal'].value+"<br >";
    });
    

    // Attach the function lookup() to the lookupButton on the main page.
    cs441GoogleMapsViz.addEvent(document.getElementById('lookupButton'), 'click', function() {
	if ($("#radio-zip").is(":checked")){
	    cs441GoogleMapsViz.lookup(layerArray, geocoder);
	}
	else {
	    console.log("About to regionalize");
	    cs441GoogleMapsViz.regionalize(layerArray, geocoder);
	}
	cs441GoogleMapsViz.setStudentLayer(studentLayer);
    });


    // Attach the function toggleLayers() to the toggleButton on the main page.
    /*cs441GoogleMapsViz.addEvent(document.getElementById('toggleButton'), 'click', function() {
	return cs441GoogleMapsViz.toggle(layerArray);
    });*/
}

/*
 * cs441GoogleMapsViz.convertZipToState
 * 
 * given a zip code, this function return the state that corresponds to that zip code
 */
cs441GoogleMapsViz.convertZipToState = function(zip) {
	zip = zip + "";
	zip2 = parseInt(zip.substring(0,2));
	zip3 = parseInt(zip.substring(0,3));
	var state = "";
	if ((zip3 >= 995) && (zip3 <= 999)) { state = "AK";}
	else if ((zip2 >= 85) && (zip2 <= 86)) { state = "AZ";}
	else if ((zip3 >= 900) && (zip3 <= 961)) { state = "CA";}
	else if ((zip2 >= 80) && (zip2 <= 81)) { state = "CO";}
	else if ((zip3 >= 967) && (zip3 <= 968)) { state = "HI";}
	else if ((zip3 >= 832) && (zip3 <= 839)) { state = "ID";}
	else if ((zip2 >= 60) && (zip2 <= 62)) { state = "IL";}
	else if ((zip3 >= 39) && (zip3 <= 49)) { state = "ME";}
	else if ((zip3 >= 550) && (zip3 <= 567)) { state = "MN";}
	else if ((zip2 >= 68) && (zip2 <= 69)) { state = "NE";}
	else if ((zip3 >= 870) && (zip3 <= 884)){ state = "NM";}
	else if ((zip3 >= 889) && (zip3 <= 899)) { state = "NV";}
	else if (((zip2 >= 10) && (zip2 <= 14)) || zip3 == 5) { state = "NY";}
	else if (zip2 == 97) { state = "OR";}
	else if (((zip2 >= 75) && (zip2 <= 79)) || (zip3 == 885)) { state = "TX";}
	else if (zip2 == 84) { state = "UT";}
	else if ((zip3 >= 980) && (zip3 <= 994)){ state = "WA";}
	else{
		//Do nothing
	}
	return state;
}
// Setup an event listener to execute the init() function for this namespace
// upon page load.
google.maps.event.addDomListener(window, 'load', cs441GoogleMapsViz.initialize);
